﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ColorPicker.Classes;
using System.Windows.Media.Imaging;

namespace ColorPicker
{
    public partial class CtrlColorPicker : UserControl
    {
        public event EventHandler<ColorPickerEVG> SelectedColorChanged;

        public Color SelectedColor
        {
            get { return _selectedColor; }
        }

        private Point cursor;
        private bool IsDragable;
        private Point clickedCursor;
        private Color _selectedColor;
        private List<Pixel> PixelsCollection = new List<Pixel>();

        public CtrlColorPicker()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(CtrlColorPicker_Loaded);
        }

        void CtrlColorPicker_Loaded(object sender, RoutedEventArgs e)
        {
            CreatePallete();

            Picker.MouseLeftButtonDown += new MouseButtonEventHandler(Picker_MouseLeftButtonDown);
            Picker.MouseLeftButtonUp += new MouseButtonEventHandler(Picker_MouseLeftButtonUp);
            Picker.MouseMove += new MouseEventHandler(Picker_MouseMove);

            ColorBar.MouseMove += new MouseEventHandler(ColorBar_MouseMove);
            ColorBar.MouseLeftButtonDown += new MouseButtonEventHandler(ColorBar_MouseLeftButtonDown);
            ColorBar.MouseLeftButtonUp += new MouseButtonEventHandler(ColorBar_MouseLeftButtonUp);

            GetSelectedColor();
        }

        void ColorBar_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            IsDragable = false;
            //ColorPickerHandle.ReleaseMouseCapture();
        }

        void ColorBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsDragable = true;
            //ColorPickerHandle.CaptureMouse();
            ColorPickerHandle.SetValue(Canvas.TopProperty, e.GetPosition(ColorBar).Y);
            SetColorFromColorBar(e.GetPosition(ColorBar));
        }

        void ColorBar_MouseMove(object sender, MouseEventArgs e)
        {
            if (IsDragable)
            {
                ColorPickerHandle.SetValue(Canvas.TopProperty, cursor.Y);
                SetColorFromColorBar(e.GetPosition(ColorBar));
            }
        }

        private void SetColorFromColorBar(Point p)
        {
            cursor = p;

            WriteableBitmap w = new WriteableBitmap(ColorBar, null);

            int colorAsInt = w.Pixels[Convert.ToInt32(cursor.Y * w.PixelWidth + cursor.X)];

            Color c = Color.FromArgb((byte)((colorAsInt >> 0x18) & 0xff),

            (byte)((colorAsInt >> 0x10) & 0xff),

            (byte)((colorAsInt >> 8) & 0xff),

            (byte)(colorAsInt & 0xff));

            primaryColor.Fill = new SolidColorBrush(c);

            GetSelectedColor();
        }

        void Picker_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            IsDragable = false;
            Picker.ReleaseMouseCapture();
        }

        void Picker_MouseMove(object sender, MouseEventArgs e)
        {
            cursor = e.GetPosition(SubPalette);

            if (IsDragable)
            {
                if (cursor.X < SubPalette.ActualWidth && cursor.X > 0 && cursor.Y < SubPalette
                .ActualHeight && cursor.Y > 0)
                {
                    double x = cursor.X - clickedCursor.X;
                    double y = cursor.Y - clickedCursor.Y;

                    if (x > 0)
                        Picker.SetValue(Canvas.LeftProperty, x);

                    if (y > 0)
                        Picker.SetValue(Canvas.TopProperty, y);

                    GetSelectedColor();
                }
            }
        }

        void Picker_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsDragable = true;
            Picker.CaptureMouse();
            clickedCursor = e.GetPosition(Picker);
        }

        private void BuildBitmap()
        {
            int imageWidth = 1;
            int imageHeight = 306;

            int count = 0;

            WriteableBitmap b = new WriteableBitmap(imageWidth, imageHeight);
            for (int x = 0; x < imageWidth; x++)
            {
                for (int y = 0; y < imageHeight; y++)
                {
                    // generate a color in 32bit format

                    Pixel p = PixelsCollection[count];

                    byte[] components = new byte[4];
                    components[0] = p.B;//(byte)(x % 255);        // blue
                    components[1] = p.G;//(byte)(y % 255);        // green
                    components[2] = p.R;//(byte)(x * y % 255);    // red
                    components[3] = p.A;//255;      // unused

                    int pixelValue = BitConverter.ToInt32(components, 0);

                    // Set the value for the 
                    b.Pixels[x * imageHeight + y] = pixelValue;
                    count++;
                }
            }

            b.Invalidate();
            ColorBar.Source = b;
        }

        private void CreatePallete()
        {
            int Range = 51;
            int ColorIncrement = 5;

            int RedChannel = 255;
            int GreenChannel = 0;
            int BlueChannel = 0;

            //red maximum
            //Increase Green Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                GreenChannel = GreenChannel + ColorIncrement;

                PixelsCollection.Add(p);
            }
            //green maximum
            //Decrease Red Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                RedChannel = RedChannel - ColorIncrement;

                PixelsCollection.Add(p);
            }

            // green maximum
            //Increase Blue Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                BlueChannel = BlueChannel + ColorIncrement;

                PixelsCollection.Add(p);
            }

            // blue maximum
            //Decrease Green Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                GreenChannel = GreenChannel - ColorIncrement;

                PixelsCollection.Add(p);
            }

            // blue maximum
            //Increase Red Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                RedChannel = RedChannel + ColorIncrement;

                PixelsCollection.Add(p);
            }

            // red maximum
            //Decrease Blue Channel
            for (int v = 0; v < Range; v++)
            {
                Pixel p = new Pixel();
                p.A = (byte)255;
                p.R = (byte)RedChannel;
                p.G = (byte)GreenChannel;
                p.B = (byte)BlueChannel;

                BlueChannel = BlueChannel - ColorIncrement;

                PixelsCollection.Add(p);
            }

            BuildBitmap();
        }

        private void GetSelectedColor()
        {
            GeneralTransform gt = Picker.TransformToVisual(SubPalette);
            Point offset = gt.Transform(new Point(0, 0));

            WriteableBitmap w = new WriteableBitmap(SubPalette, null);

            int colorAsInt = w.Pixels[Convert.ToInt32(offset.Y * w.PixelWidth + offset.X)];

            Color c = Color.FromArgb((byte)((colorAsInt >> 0x18) & 0xff),

            (byte)((colorAsInt >> 0x10) & 0xff),

            (byte)((colorAsInt >> 8) & 0xff),

            (byte)(colorAsInt & 0xff));

            _selectedColor = c;

            if (SelectedColorChanged != null)
                SelectedColorChanged(this, new ColorPickerEVG(SelectedColor));
        }
    }
}
